import threading
from datetime import datetime
import irc.client

from kivy.logger import Logger

from amgineirc.viewModel.viewModel import ViewModel
from amgineirc.viewModel.channels.clientEventHandlerViewModel import ClientEventHandlerViewModel


class SendReceiveViewModel(ViewModel, ClientEventHandlerViewModel):

    def __init__(self, view, send_view, receive_view, connection, target, appdata):
        ViewModel.__init__(self, view)
        ClientEventHandlerViewModel.__init__(self, connection, target, appdata)
        # the send view
        self._send_view = send_view
        self._send_view.vm_bind_on_send(self.handle_view_send)
        # the receive view
        self._receive_view = receive_view
        # this users nick on this server connection
        self._nick = ''

    def _send_privmsg(self, target, message=''):
        # message is user input
        # if this message goes to another user
        #   then open a window for this private message if not already open
        msg = message[:480]
        if target != self._target:
            self._appdata['connection_vm'].add_privmsg_connection(self._connection,
                                                                  target,
                                                                  send_message=msg)
        else:
            # this message goes to this channel
            if len(msg):
                self._connection.privmsg(target, msg)
                # get the nick for this server
                record = self._appdata['servers'].get_server(self._connection.server)
                if record is not None:
                    nick = record['nick']
                else:
                    nick = ''
                # handle as user input for display back to the user
                display_source = 'You to %s' % self.target
                self.handle_client_event(self._connection.server,
                                         self._target,
                                         'input',
                                         display_source,
                                         [msg])

    def _handle_view_send_privmsg(self, m):
        if m[0] != '/':
            self._send_privmsg(self._target, m)
            return True
        elif m[:4] == '/msg':
            # /msg somenick hey there
            # same as '/privmsg <target> <message>'
            args = m[5:].split(None, 1)
            if len(args) == 2:
                self._send_privmsg(*args)
            return True
        elif m[:8] == '/privmsg':
            # /privmsg <target> <optional message>
            # buttons only send /privmsg <target>
            args = m[9:].split(None, 1)
            if len(args) >= 1:
                self._send_privmsg(*args)
            return True
        # not a privmsg
        return False

    def handle_view_send(self, m):
        """ the user has entered text to send.
        send the message over the network.
        """
        if not self.connected:
            return False
        try:
            if m[:7] == '/admin ':
                server = m[7:].strip()
                self._connection.admin(server)
            elif m[:6] == '/away ':
                self._connection.send_raw(m)
            elif m[:5] == '/cap ':
                args = m[5:].split()
                if len(args) > 0:
                    self._connection.cap(args[0], args[1:])
            elif m[:6] == '/ctcp ':
                args = m[6:].split()
                largs == len(args)
                if largs == 2 or largs == 3:
                    self._connection.ctcp(*args)
            elif m[:12] == '/ctcp_reply ':                    
                args = m[12:].split()
                if len(args) == 2:
                    self._connection.ctcp_reply(*args)
            elif m[:9] == '/globops ':                    
                msg = m[9:].strip()
                if len(msg) > 0:
                    self._connection.globops(msg)
            elif m[:6] == '/info ':                    
                self._connection.info(m[6:].strip())
            elif m[:8] == '/invite ':                    
                args = m[8:].split()
                if len(args) == 2:
                    self._connection.invite(*args)
            elif m[:6] == '/ison ':                    
                args = m[6:].split()
                if len(args) > 0:
                    self._connection.ison(*args)
            elif m[:6] == '/join ':
                args = m[6:].split(None)
                if len(args) == 1 or len(args) == 2:
                    # open the views for the channels
                    channels = [i.strip() for i in args[0].split(',')]
                    for i in channels:
                        self._appdata['connection_vm'].add_channel_connection(self._connection, i)
                    # send the command
                    self._connection.join(*args)
            elif m[:6] == '/kick ':                    
                args = m[6:].split(None, 2)
                if len(args) > 1:
                    self._connection.kick(*args)
            elif m[:7] == '/links ':                    
                args = m[7:].split(None, 1)
                self._connection.links(*args)
            elif m[:5] == '/list':                    
                    self._connection.list()
            elif m[:5] == '/list':                    
                channels = []
                server = ''
                args = m[6:].split(None)
                if len(args) > 0:
                    if ',' in args[0]:
                        channels = args[0].split(',')
                        if len(args) == 2:
                            server = args[1]
                    else:
                        if irc.client.is_channel(args[0]):
                            channels.append(args[0])
                            if len(args) == 2:
                                server = args[1]
                        else:
                            server = args[0]
                self._connection.list(channels, server)
            elif m[:8] == '/lusers ':                    
                self._connection.lusers(m[8:].strip())
            elif m[:6] == '/mode ':                    
                args = m[6:].split()
                if len(args) == 2:
                    self._connection.mode(*args)
            elif m[:5] == '/motd':                    
                self._connection.motd(m[6:].strip())
            elif m[:6] == '/names':                    
                args = m[7:].split(None)
                channels = []
                server = ''
                for i in args:
                    if irc.client.is_channel(i):
                        channels.append(i)
                self._connection.names(channels)
            elif m[:6] == '/nick ':                    
                self._connection.nick(m[6:].strip())
            elif m[:8] == '/notice ':
                args = m[8:].split(None, 1)
                if len(args) == 2:
                    self._connection.notice(*args)
                elif len(args) == 1:
                    self._connection.notice(self._target, args[1])
            elif m[:6] == '/oper ':
                args = m[6:].split(None, 1)
                if len(args) == 2:
                    self._connection.oper(*args)
            elif m[:5] == '/part':
                args = m[6:].split(None, 1)
                largs = len(args)
                if largs == 0:
                        args.append(self._target)
                if largs == 1 or largs == 2:
                    self._connection.part(*args)
            elif m[:6] == '/pass ':
                self._connection.pass_(m[6:].strip())
            elif m[:6] == '/ping ':
                args = m[6:].split(None, 1)
                largs = len(args)
                if largs == 1 or largs == 2:
                    self._connection.ping(*args)
            elif m[:6] == '/pong ':
                args = m[6:].split(None, 1)
                largs = len(args)
                if largs == 1 or largs == 2:
                    self._connection.pong(*args)
            elif m[:5] == '/quit':
                msg = m[6:400] + ' : ' + self._appdata['quit_message']
                self._connection.quit(msg)
            elif m[:5] == '/who ':
                args = m[5:].split()
                if len(args) <= 2:
                    self._connection.whois(args)
            elif m[:7] == '/whois ':
                args = [i.strip() for i in m[7:].split(',')]
                self._connection.whois(args)
            elif m[:8] == '/whowas ':
                args = m[8:].split()
                if len(args) <= 3:
                    self._connection.whois(args)
            else:
                # unknown IRC command
                return False
            return True
        except Exception as e:
            message = repr(e)
            self.handle_client_event(self._connection.server, self._target, 'exception', '', [message])

    def w_handle_command(self, command, target):
        # a command from a button
        self.handle_view_send(command + ' ' + target)

    # client methods
    
    def _format_new_log_entry(self, type, target, source, text_list):
        dt = datetime.now()
        tstamp = dt.strftime('%a %b %d - %I:%M:%S %p')
        if self._appdata['debug']:
            return "type:%s, to:%s, from:%s : %s\n%s" % (type, target, source, tstamp, ' '.join(text_list))
        else:
            # not debugging
            return '<%s> %s\n%s' % (source, tstamp, ' '.join(text_list))

    def handle_on_connect(self, connection):
        ClientEventHandlerViewModel.handle_on_connect(self, connection)
        self._send_view.vm_set_state(connected=True)
        self._receive_view.vm_set_state(connected=True)
        # get the nick for this server
        record = self._appdata['servers'].get_server(self._connection.server)
        if record is not None:
            self._nick = record['nick']
        else:
            self._nick = ''

    def handle_on_disconnect(self):
        self._send_view.vm_set_state(connected=False)
        self._receive_view.vm_set_state(connected=False)
        ClientEventHandlerViewModel.handle_on_disconnect(self)
